/*
 *  Copyright (c) 2022 ZhuHai Jieli Technology Co.,Ltd.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*********************************************************************************************
    *   Filename        : p33.c

    *   Description     :

    *   Author          : Longshusheng

    *   Email           : Longshusheng@zh-jieli.com

    *   Last modifiled  : 2018-06-04 15:50

    *   Copyright:(c)JIELI  2011-2017  @ , All Rights Reserved.
*********************************************************************************************/
#include "power/p33.h"
#include "cpu.h"
#include "power_hw.h"

#define LOG_TAG_CONST       P33
#define LOG_TAG             "[P33]"
#include "debug.h"

// p33 function
#if 1
AT(.volatile_ram_code)
u8 p33_buf(u8 buf)
{
    JL_P33->SPI_DAT = buf;
    JL_P33->SPI_CON |= BIT(4);

    while (JL_P33->SPI_CON & BIT(1)) {
    }
    return JL_P33->SPI_DAT;
}

void p33_xor_1byte(u16 addr, u8 data0)
{
    p33_cs_h(addr);
    p33_buf((P33_XOR << 5) | (u8)((addr & 0x300) >> 8));               // rd    //adr 3
    p33_buf((u8)(addr & 0xff));       // wr    //adr 3
    p33_buf(data0);
    p33_cs_l;
}

AT(.volatile_ram_code)
void p33_and_1byte(u16 addr, u8 data0)
{
    p33_cs_h(addr);
    p33_buf((P33_AND << 5) | (u8)((addr & 0x300) >> 8));               // rd    //adr 3
    p33_buf((u8)(addr & 0xff));       // wr    //adr 3
    p33_buf(data0);
    p33_cs_l;
}

AT(.volatile_ram_code)
void p33_or_1byte(u16 addr, u8 data0)
{
    p33_cs_h(addr);
    p33_buf((P33_OR << 5) | (u8)((addr & 0x300) >> 8));               // rd    //adr 3
    p33_buf((u8)(addr & 0xff));       // wr    //adr 3
    p33_buf(data0);
    p33_cs_l;
}

AT(.volatile_ram_code)
void p33_tx_1byte(u16 addr, u8 data0)
{
    p33_cs_h(addr);
    p33_buf((u8)((addr & 0x300) >> 8));               // rd    //adr 3
    p33_buf((u8)(addr & 0xff));       // wr    //adr 3
    p33_buf(data0);
    p33_cs_l;
}

AT(.volatile_ram_code)
u8 p33_rx_1byte(u16 addr)
{
    u8 data;

    p33_cs_h(addr);
    p33_buf(BIT(7) | (u8)((addr & 0x300) >> 8));               // rd    //adr 3
    p33_buf((u8)(addr & 0xff));       // wr    //adr 3
    data = p33_buf(0x5e);
    p33_cs_l;
    return data;
}

AT(.volatile_ram_code)
void P33_CON_SET(u16 addr, u8 start, u8 len, u8 data)
{
    u8 reg = 0;
    reg = p33_rx_1byte(addr);
    SFR(reg, start, len, data);
    p33_tx_1byte(addr, reg);
}
#endif

// for P33_WLDO06_AUTO
AT(.volatile_ram_code)
void SET_WVDD_LEV(u8 lev)
{
    // 0(0.728v)  1(0.696v) 2(0.648v) 3(0.605v) 4(0.571v) 5(0.537v) 6(0.501v) 7(0.467v)
    p33_tx_1byte(P3_WLDO06_AUTO, pd_wldo06_auto_init | (lev << 5));
}

u8 READ_PMU_RESET_SOURCE(void)
{
    return P33_CON_GET(P3_RST_SRC);
}

AT(.volatile_ram_code)
void NV_RAM_POWER_GATE(u8 sw)
{
    if (sw) {
        P33_TX_NBIT(P3_IVS_SET, BIT(4), 1);
    } else {
        P33_TX_NBIT(P3_IVS_CLR, BIT(4), 1);
    }
}

void RESET_MASK_SW(u8 sw)
{
    if (sw) {
        P33_TX_NBIT(P3_IVS_CLR, BIT(5), 1);
    } else {
        P33_TX_NBIT(P3_IVS_SET, BIT(5), 1);
    }
}

void close_32K(u8 keep_osci_flag)
{
    if (keep_osci_flag) {
        P33_CON_SET(P3_OSL_CON, 0, 8, 0x03);
    } else {
        P33_CON_SET(P3_OSL_CON, 0, 8, 0x00);
    }
}
/*******************************************************************/

void sdpg_config(int enable)
{
    if (enable) {
        JL_PORTB->DIE |= BIT(11);
        JL_PORTB->DIR |= BIT(11);
        JL_PORTB->PU |= BIT(11);
        delay(100);
        p33_tx_1byte(P3_SDPG_CON, 0b1010);
        JL_PORTB->OUT |= BIT(11);
        JL_PORTB->DIR &= ~BIT(11);
        JL_PORTB->HD |= BIT(11);
        JL_PORTB->HD0 |= BIT(11);
        delay(100);
        p33_tx_1byte(P3_SDPG_CON, 0b01);
    } else {
        p33_tx_1byte(P3_SDPG_CON, 0);
        JL_PORTB->DIR |= BIT(11);
        JL_PORTB->PU &= ~BIT(11);
        JL_PORTB->PD &= ~BIT(11);
        JL_PORTB->HD &= ~BIT(11);
        JL_PORTB->HD0 &= ~BIT(11);
        JL_PORTB->DIE &= ~BIT(11);
    }
}
void adc_pmu_ch_select(u32 ch)
{
    // 0:VBG  1:VDC13  2:SYSVDD  3:VTEMP  4:PROGF  5:1/4 VBAT 6:1/4 LDO5V  7:WVDD
    P33_CON_SET(P3_ANA_CON4, 1, 3, ch);
}
void adc_pmu_detect_en(u32 en)
{
    P33_CON_SET(P3_ANA_CON4, 4, 1, 0);
    P33_CON_SET(P3_ANA_CON4, 0, 1, en);
}
static u8 vdc13_lev;
void adc_vdc13_save(void)
{
    vdc13_lev = GET_VD13_HD_SEL();
    VDC13_VOL_SEL(0b110);
}
void adc_vdc13_restore(void)
{
    VDC13_VOL_SEL(vdc13_lev);
}
